home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / unixcpio.gz / unixnet.cpio / ax25subr.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  11KB  |  480 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "timer.h"
  5. #include "ax25.h"
  6. #include "lapb.h"
  7. #include "netuser.h"
  8. #include "ftp.h"
  9. #include "telnet.h"
  10. #include "iface.h"
  11. #include "finger.h"
  12. #include <ctype.h>
  13. #ifdef    UNIX
  14. #undef    toupper
  15. #undef    tolower
  16. #include <string.h>
  17. #include <memory.h>
  18. #endif
  19.  
  20. struct ax25_cb *ax25_cb[NHASH];
  21.  
  22. /* Default AX.25 parameters */
  23. int16 t1init = 10000 / MSPTICK;    /* FRACK of 10 seconds */
  24. int16 t2init = 1000 / MSPTICK;    /* 1 sec acknowledgment delay */
  25. int16 t3init = 0 / MSPTICK;    /* No keep-alive polling */
  26. int16 maxframe = 1;        /* Stop and wait */
  27. int16 n2 = 10;            /* 10 retries */
  28. int16 axwindow = 2048;        /* 2K incoming text before RNR'ing */
  29. int16 paclen = 256;        /* 256-byte I fields */
  30. int16 pthresh = 128;        /* Send polls for packets larger than this */
  31.  
  32. /* Address hash function. Exclusive-ORs each byte, ignoring
  33.  * such insignificant, annoying things as E and H bits
  34.  */
  35. static
  36. int16
  37. ax25hash(s)
  38. struct ax25_addr *s;
  39. {
  40.     register char x;
  41.     register int i;
  42.     register char *cp;
  43.  
  44.     x = 0;
  45.     cp = s->call;
  46.     for(i=ALEN; i!=0; i--)
  47.         x ^= *cp++ & 0xfe;
  48.     x ^= s->ssid & SSID;
  49.     return uchar(x) % NHASH;
  50. }
  51. /* Look up entry in hash table */
  52. struct ax25_cb *
  53. find_ax25(addr)
  54. register struct ax25_addr *addr;
  55. {
  56.     int16 hashval;
  57.     register struct ax25_cb *axp;
  58.     char i_state;
  59.  
  60.     /* Find appropriate hash chain */
  61.     hashval = ax25hash(addr);
  62.  
  63.     /* Search hash chain */
  64.     i_state = disable();
  65.     for(axp = ax25_cb[hashval]; axp != NULLAX25; axp = axp->next){
  66.         if(addreq(&axp->addr.dest,addr)){
  67.             restore(i_state);
  68.             return axp;
  69.         }
  70.     }
  71.     restore(i_state);
  72.     return NULLAX25;
  73. }
  74.  
  75. /* Remove address entry from hash table */
  76. del_ax25(axp)
  77. register struct ax25_cb *axp;
  78. {
  79.     int16 hashval;
  80.     char i_state;
  81.  
  82.     if(axp == NULLAX25)
  83.         return;
  84.     /* Remove from hash header list if first on chain */
  85.     hashval = ax25hash(&axp->addr.dest);
  86.     i_state = disable();
  87.  
  88.     /* Remove from chain list */
  89.     if(ax25_cb[hashval] == axp)
  90.         ax25_cb[hashval] = axp->next;
  91.     if(axp->prev != NULLAX25)
  92.         axp->prev->next = axp->next;
  93.     if(axp->next != NULLAX25)
  94.         axp->next->prev = axp->prev;
  95.  
  96.     /* Timers should already be stopped, but just in case... */
  97.     stop_timer(&axp->t1);
  98.     stop_timer(&axp->t2);
  99.     stop_timer(&axp->t3);
  100.  
  101.     /* Free allocated resources */
  102.     free_q(&axp->txq);
  103.     free_q(&axp->rxasm);
  104.     free_q(&axp->rxq);
  105.     free((char *)axp);
  106.  
  107.     restore(i_state);
  108. }
  109.  
  110. /* Create an ax25 control block. Allocate a new structure, if necessary,
  111.  * and fill it with all the defaults. The caller
  112.  * is still responsible for filling in the reply address
  113.  */
  114. struct ax25_cb *
  115. cr_ax25(addr)
  116. struct ax25_addr *addr;
  117. {
  118.     void recover(),send_ack(),pollthem(),ax_incom();
  119.     register struct ax25_cb *axp;
  120.     int16 hashval;
  121.     char i_state;
  122. #ifdef SID2
  123.     void mbx_state();
  124. #endif
  125.  
  126.     if(addr == NULLAXADDR)
  127.         return NULLAX25;
  128.  
  129.     if((axp = find_ax25(addr)) == NULLAX25){
  130.         /* Not already in table; create an entry
  131.          * and insert it at the head of the chain
  132.          */
  133.         /* Find appropriate hash chain */
  134.         hashval = ax25hash(addr);
  135.         i_state = disable();
  136.         axp = (struct ax25_cb *)calloc(1,sizeof(struct ax25_cb));
  137.         if(axp == NULLAX25)
  138.             return NULLAX25;
  139.         /* Insert at beginning of chain */
  140.         axp->prev = NULLAX25;
  141.         axp->next = ax25_cb[hashval];
  142.         if(axp->next != NULLAX25)
  143.             axp->next->prev = axp;
  144.         ax25_cb[hashval] = axp;
  145.         restore(i_state);
  146.     }
  147.     axp->maxframe = maxframe;
  148.     axp->window = axwindow;
  149.     axp->paclen = paclen;
  150.     axp->proto = V2;    /* Default, can be changed by other end */
  151.     axp->pthresh = pthresh;
  152.     axp->n2 = n2;
  153.     axp->t1.start = t1init;
  154.     axp->t1.func = recover;
  155.     axp->t1.arg = (char *)axp;
  156.  
  157.     axp->t2.start = t2init;
  158.     axp->t2.func = send_ack;
  159.     axp->t2.arg = (char *)axp;
  160.  
  161.     axp->t3.start = t3init;
  162.     axp->t3.func = pollthem;
  163.     axp->t3.arg = (char *)axp;
  164.  
  165. #ifdef SID2
  166.     axp->s_upcall = mbx_state;
  167. #endif
  168.     axp->r_upcall = ax_incom;
  169.     return axp;
  170. }
  171.  
  172. /*
  173.  * setcall - convert callsign plus substation ID of the form
  174.  * "KA9Q-0" to AX.25 (shifted) address format
  175.  *   Address extension bit is left clear
  176.  *   Return -1 on error, 0 if OK
  177.  */
  178. int
  179. setcall(out,call)
  180. struct ax25_addr *out;
  181. char *call;
  182. {
  183.     int csize;
  184.     unsigned ssid;
  185.     register int i;
  186.     register char *cp,*dp;
  187.     char c;
  188.  
  189.     if(out == (struct ax25_addr *)NULL || call == NULLCHAR || *call == '\0'){
  190.         return -1;
  191.     }
  192.     /* Find dash, if any, separating callsign from ssid
  193.      * Then compute length of callsign field and make sure
  194.      * it isn't excessive
  195.      */
  196.     dp = index(call,'-');
  197.     if(dp == NULLCHAR)
  198.         csize = strlen(call);
  199.     else
  200.         csize = dp - call;
  201.     if(csize > ALEN)
  202.         return -1;
  203.     /* Now find and convert ssid, if any */
  204.     if(dp != NULLCHAR){
  205.         dp++;    /* skip dash */
  206.         ssid = atoi(dp);
  207.         if(ssid > 15)
  208.             return -1;
  209.     } else
  210.         ssid = 0;
  211.     /* Copy upper-case callsign, left shifted one bit */
  212.     cp = out->call;
  213.     for(i=0;i<csize;i++){
  214.         c = *call++;
  215.         if(islower(c))
  216.             c = toupper(c);
  217.         *cp++ = c << 1;
  218.     }
  219.     /* Pad with shifted spaces if necessary */
  220.     for(;i<ALEN;i++)
  221.         *cp++ = ' ' << 1;
  222.     
  223.     /* Insert substation ID field and set reserved bits */
  224.     out->ssid = 0x60 | (ssid << 1);
  225.     return 0;
  226. }
  227. /* Set a digipeater string in an ARP table entry */
  228. setpath(out,in,cnt)
  229. char *out;    /* Target char array containing addresses in net form */
  230. char *in[];    /* Input array of tokenized callsigns in ASCII */
  231. int cnt;    /* Number of callsigns in array */
  232. {
  233.     struct ax25_addr addr;
  234.     char *putaxaddr();
  235.  
  236.     if(cnt == 0)
  237.         return;
  238.     while(cnt-- != 0){
  239.         setcall(&addr,*in++);
  240.         addr.ssid &= ~E;
  241.         out = putaxaddr(out,&addr);
  242.     }
  243.     out[-1] |= E;
  244. }
  245. addreq(a,b)
  246. register struct ax25_addr *a,*b;
  247. {
  248.     if(memcmp(a->call,b->call,ALEN) != 0)
  249.         return 0;
  250.     if((a->ssid & SSID) != (b->ssid & SSID))
  251.         return 0;
  252.     return 1;
  253. }
  254. /* Convert encoded AX.25 address to printable string */
  255. pax25(e,addr)
  256. char *e;
  257. struct ax25_addr *addr;
  258. {
  259.     register int i;
  260.     char c,*cp;
  261. #ifdef    BSD
  262.     char *sprintf();
  263. #endif
  264.  
  265.     cp = addr->call;
  266.     for(i=ALEN;i != 0;i--){
  267.         c = (*cp++ >> 1) & 0x7f;
  268.         if(c == ' ')
  269.             break;
  270.         *e++ = c;
  271.     }
  272.     if ((addr->ssid & SSID) != 0)
  273.         sprintf(e,"-%d",(addr->ssid >> 1) & 0xf);    /* ssid */
  274.     else
  275.         *e = 0;
  276. }
  277. /* Print a string of AX.25 addresses in the form
  278.  * "KA9Q-0 [via N4HY-0,N2DSY-2]"
  279.  * Designed for use by ARP - arg is a char string
  280.  */
  281. psax25(e,addr)
  282. register char *e;
  283. register char *addr;
  284. {
  285.     int i;
  286.     struct ax25_addr axaddr;
  287.     char tmp[16];
  288.     char *getaxaddr();
  289.  
  290.     e[0] = '\0';    /* Give strcat a staritng point */
  291.     for(i=0;;i++){
  292.         /* Create local copy in host-format structure */
  293.         addr = getaxaddr(&axaddr,addr);
  294.  
  295.         /* Create ASCII representation and append to output */
  296.         pax25(tmp,&axaddr);
  297.         strcat(e,tmp);
  298.  
  299.         if(axaddr.ssid & E)
  300.             break;
  301.         if(i == 0)
  302.             strcat(e," via ");
  303.         else
  304.             strcat(e,",");
  305.         /* Not really necessary, but speeds up subsequent strcats */
  306.         e += strlen(e);
  307.     }
  308. }
  309. char *
  310. getaxaddr(ap,cp)
  311. register struct ax25_addr *ap;
  312. register char *cp;
  313. {
  314.     memcpy(ap->call,cp,ALEN);
  315.     cp += ALEN;
  316.     ap->ssid = *cp++;
  317.     return cp;
  318. }
  319. char *
  320. putaxaddr(cp,ap)
  321. register char *cp;
  322. register struct ax25_addr *ap;
  323. {
  324.     memcpy(cp,ap->call,ALEN);
  325.     cp += ALEN;
  326.     *cp++ = ap->ssid;
  327.     return cp;
  328. }
  329.  
  330. /* Convert a host-format AX.25 header into a mbuf ready for transmission */
  331. struct mbuf *
  332. htonax25(hdr,data)
  333. register struct ax25 *hdr;
  334. struct mbuf *data;
  335. {
  336.     struct mbuf *bp;
  337.     register char *cp;
  338.     register int16 i;
  339.  
  340.     if(hdr == (struct ax25 *)NULL || hdr->ndigis > MAXDIGIS)
  341.         return NULLBUF;
  342.  
  343.     /* Allocate space for return buffer */
  344.     i = AXALEN * (2 + hdr->ndigis);
  345.     if((bp = pushdown(data,i)) == NULLBUF)
  346.         return NULLBUF;
  347.  
  348.     /* Now convert */
  349.     cp = bp->data;
  350.  
  351.     hdr->dest.ssid &= ~E;    /* Dest E-bit is always off */
  352.     /* Encode command/response in C bits */
  353.     switch(hdr->cmdrsp){
  354.     case COMMAND:
  355.         hdr->dest.ssid |= C;
  356.         hdr->source.ssid &= ~C;
  357.         break;
  358.     case RESPONSE:
  359.         hdr->dest.ssid &= ~C;
  360.         hdr->source.ssid |= C;
  361.         break;
  362.     default:
  363.         hdr->dest.ssid &= ~C;
  364.         hdr->source.ssid &= ~C;
  365.         break;
  366.     }
  367.     cp = putaxaddr(cp,&hdr->dest);
  368.  
  369.     /* Set E bit on source address if no digis */
  370.     if(hdr->ndigis == 0){
  371.         hdr->source.ssid |= E;
  372.         putaxaddr(cp,&hdr->source);
  373.         return bp;
  374.     }
  375.     hdr->source.ssid &= ~E;
  376.     cp = putaxaddr(cp,&hdr->source);
  377.  
  378.     /* All but last digi get copied with E bit off */
  379.     for(i=0; i < hdr->ndigis - 1; i++){
  380.         hdr->digis[i].ssid &= ~E;
  381.         cp = putaxaddr(cp,&hdr->digis[i]);
  382.     }
  383.     hdr->digis[i].ssid |= E;
  384.     cp = putaxaddr(cp,&hdr->digis[i]);
  385.     return bp;
  386. }
  387. /* Convert an AX.25 ARP table entry into a host format address structure
  388.  * ready for use in transmitting a packet
  389.  */
  390. int
  391. atohax25(hdr,hwaddr,source)
  392. register struct ax25 *hdr;
  393. register char *hwaddr;
  394. struct ax25_addr *source;
  395. {
  396.     extern struct ax25_addr mycall;
  397.     register struct ax25_addr *axp;
  398.  
  399.     hwaddr = getaxaddr(&hdr->dest,hwaddr);    /* Destination address */
  400.     ASSIGN(hdr->source,*source);        /* Source address */
  401.     if(hdr->dest.ssid & E){
  402.         /* No digipeaters */
  403.         hdr->ndigis = 0;
  404.         hdr->dest.ssid &= ~E;
  405.         hdr->source.ssid |= E;
  406.         return 2;
  407.     }
  408.     hdr->source.ssid &= ~E;
  409.     hdr->dest.ssid &= ~E;
  410.     for(axp = hdr->digis; axp < &hdr->digis[MAXDIGIS]; axp++){
  411.         hwaddr = getaxaddr(axp,hwaddr);
  412.         if(axp->ssid & E){
  413.             hdr->ndigis = axp - hdr->digis + 1;
  414.             return hdr->ndigis;
  415.         }
  416.     }
  417.     return -1;
  418. }
  419. /* Convert a network-format AX.25 header into a host format structure
  420.  * Return -1 if error, number of addresses if OK
  421.  */
  422. int
  423. ntohax25(hdr,bpp)
  424. register struct ax25 *hdr;    /* Output structure */
  425. struct mbuf **bpp;
  426. {
  427.     register struct ax25_addr *axp;
  428.     char *getaxaddr();
  429.     char buf[AXALEN];
  430.  
  431.     if(pullup(bpp,buf,AXALEN) < AXALEN)
  432.         return -1;
  433.     getaxaddr(&hdr->dest,buf);
  434.  
  435.     if(pullup(bpp,buf,AXALEN) < AXALEN)
  436.         return -1;
  437.     getaxaddr(&hdr->source,buf);
  438.  
  439.     /* Process C bits to get command/response indication */
  440.     if((hdr->source.ssid & C) == (hdr->dest.ssid & C))
  441.         hdr->cmdrsp = UNKNOWN;
  442.     else if(hdr->source.ssid & C)
  443.         hdr->cmdrsp = RESPONSE;
  444.     else
  445.         hdr->cmdrsp = COMMAND;
  446.  
  447.     hdr->ndigis = 0;
  448.     if(hdr->source.ssid & E)
  449.         return 2;    /* No digis */
  450.  
  451.     /* Process digipeaters */
  452.     for(axp = hdr->digis;axp < &hdr->digis[MAXDIGIS]; axp++){
  453.         if(pullup(bpp,buf,AXALEN) < AXALEN)
  454.             return -1;
  455.         getaxaddr(axp,buf);
  456.         if(axp->ssid & E){    /* Last one */
  457.             hdr->ndigis = axp - hdr->digis + 1;
  458.             return hdr->ndigis + 2;            
  459.         }
  460.     }
  461.     return -1;    /* Too many digis */
  462. }
  463.  
  464. /* Figure out the frame type from the control field
  465.  * This is done by masking out any sequence numbers and the
  466.  * poll/final bit after determining the general class (I/S/U) of the frame
  467.  */
  468. int16
  469. ftype(control)
  470. register char control;
  471. {
  472.     if((control & 1) == 0)    /* An I-frame is an I-frame... */
  473.         return I;
  474.     if(control & 2)        /* U-frames use all except P/F bit for type */
  475.         return(control & ~PF);
  476.     else            /* S-frames use low order 4 bits for type */
  477.         return(control & 0xf);
  478. }
  479.  
  480.